package com.jasiri.project.lib.dev.util

import android.annotation.SuppressLint
import android.app.ActivityManager
import android.content.Context
import android.graphics.ImageFormat
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraManager
import android.net.ConnectivityManager
import android.os.Environment
import android.os.StatFs
import android.util.Base64
import java.io.ByteArrayOutputStream
import java.math.BigDecimal
import java.math.RoundingMode
import java.net.NetworkInterface
import java.net.SocketException
import java.nio.charset.StandardCharsets
import java.util.zip.GZIPOutputStream
import kotlin.math.max


fun String?.checkToString(): String {
    return this ?: ""
}

fun Int.checkToInt(): Int {
    return max(this, 0)
}

fun String?.checkToLong(): Long {
    if (this.isNullOrBlank()) return 0L
    return try {
        this.toLong()
    } catch (e: Exception) {
        0L
    }
}

fun String.formatZipString(): String {
    if (isBlank()) return ""

    return try {
        val utf8Bytes = this.toByteArray(StandardCharsets.UTF_8)
        ByteArrayOutputStream().use { outputStream ->
            GZIPOutputStream(outputStream).apply {
                write(utf8Bytes)
                close()
            }
            Base64.encodeToString(outputStream.toByteArray(), Base64.URL_SAFE or Base64.NO_WRAP or Base64.NO_PADDING)
        }
    } catch (e: Exception) {
        ""
    }
}

fun getCommonData1(paramContext: Context): String {
    return try {
        val memoryInfo = ActivityManager.MemoryInfo()
        (paramContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).getMemoryInfo(
            memoryInfo
        )
        formatSysSize(memoryInfo.totalMem.toFloat(), 1024f)
    } catch (e: java.lang.Exception) {
        //
        "0"
    }
}

fun getCommonData2(): String {
    return try {
        val file = Environment.getDataDirectory()
        val statFs = StatFs(file.path)
        formatSysSize(
            (statFs.blockCountLong * statFs.blockSizeLong).toFloat(),
            1024f
        )
    } catch (e: java.lang.Exception) {
        //
        "0"
    }
}

fun formatSysSize(size: Float, unit: Float): String {
    val units = arrayOf("B", "KB", "MB", "GB", "TB")
    var index = 0
    var newSize = size
    while (newSize > unit && index < 4) {
        newSize /= unit
        index++
    }
    val resultDec = BigDecimal(newSize.toDouble())
        .setScale(2, RoundingMode.HALF_UP)
    return "${resultDec.toPlainString()}${units[index]}"
}

fun getCommonData3(context: Context): String {
    val cameraId = getCommonData7(context)
    return getCommonData9(context, cameraId)
}

fun getCommonData4(context: Context): String {
    val cameraId = getCommonData8(context)
    return getCommonData9(context, cameraId)
}

fun getCommonData5(): String {
    var macAddress = ""
    try {
        val interfaces = NetworkInterface.getNetworkInterfaces()
        while (interfaces.hasMoreElements()) {
            val networkInterface = interfaces.nextElement()
            val hardwareAddress = networkInterface.hardwareAddress
            if (hardwareAddress != null && hardwareAddress.isNotEmpty()) {
                val stringBuilder = StringBuilder()
                for (b in hardwareAddress) {
                    stringBuilder.append(String.format("%02X:", b))
                }
                if (stringBuilder.isNotEmpty()) {
                    stringBuilder.deleteCharAt(stringBuilder.length - 1)
                }
                var currentMac = stringBuilder.toString()
                if (!networkInterface.name.equals("wlan0", ignoreCase = true)) {
                    currentMac = macAddress
                }
                macAddress = currentMac
            }
        }
    } catch (e: SocketException) {
        e.printStackTrace()
    }
    return macAddress
}

@SuppressLint("ServiceCast")
fun getCommonData6(context: Context): String {
    return try {
        val connectivityManager =
            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val network = connectivityManager.activeNetworkInfo
        if (network != null && network.isConnected) {
            when (network.type) {
                ConnectivityManager.TYPE_WIFI -> "WIFI"
                ConnectivityManager.TYPE_MOBILE -> "MOBILE"
                else -> ""
            }
        } else {
            ""
        }
    } catch (e: Exception) {
        e.printStackTrace()
        ""
    }
}

private fun getCommonData7(context: Context): Int {
    var cid = -1
    val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
    try {
        val cameraIds = cameraManager.cameraIdList
        for (cID in cameraIds) {
            if (cID == CameraCharacteristics.LENS_FACING_BACK.toString()) {
                cid = cID.toInt()
                break
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return cid
}

private fun getCommonData8(context: Context): Int {
    var cid = -1
    try {
        val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
        val cameraIds = cameraManager.cameraIdList
        for (cID in cameraIds) {
            if (cID == CameraCharacteristics.LENS_FACING_FRONT.toString()) {
                cid = cID.toInt()
                break
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return cid
}

private fun getCommonData9(context: Context, paramInt: Int): String {
    var pixelValue = "0"
    if (paramInt == -1)
        return pixelValue

    try {
        val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
        val cameraCharacteristics = cameraManager.getCameraCharacteristics(paramInt.toString())
        val streamConfigurationMap =
            cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
        val sizes = streamConfigurationMap?.getOutputSizes(ImageFormat.JPEG)
        if (!sizes.isNullOrEmpty()) {
            val fistSize = sizes[0]
            val gWidth = fistSize.width
            val gHeight = fistSize.height
            val pixels = (gWidth * gHeight / 10000)
            pixelValue = pixels.toString()
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return pixelValue
}


